
hook.Add("UpdateData", "gStats.UpdateData", function( tbl )
	if tbl[1]:IsBot() then return end
	MsgN("\nHook Alias: UpdateData\nDescription: Tells the SERVER when vars are changed.\nSyntax: hook.Add('UpdateData', 'gStats.UpdateData', function( tbl )\n")
	for k, v in pairs(tbl) do
		if type(v) == "boolean" or type(v) == "number" or type(v) == "string" then
			MsgN("gStats.UpdateData -- " .. v)
		end
	end
end)

hook.Add("SetData", "gStats.SetData", function( oldtbl, newtbl )
	if oldtbl[1]:IsBot() then return end
	MsgN("\nHook Alias: SetData\nDescriptiono: Tells the SERVER when data is saved to mysql and what is changed.\nSyntax: hook.Add('SetData', 'gStats.SetData', function( oldtbl, newtbl )\n")
	for k, v in pairs(oldtbl) do
		if type(v) == "boolean" or type(v) == "number" or type(v) == "string" then
			MsgN("gStats.SetData -- old -- " .. v)
		end
	end
	for k, v in pairs(newtbl) do
		if type(v) == "boolean" or type(v) == "number" or type(v) == "string" then
			MsgN("gStats.SetData -- new -- " .. v)
		end
	end
end)

hook.Add("PlayerInitialSpawn", "gStats.PlayerInitialSpawn", function( p )
	p:GetData()
	umsg.Start("gStats.AllowSpectate", p)
		umsg.Bool(SpectatorStats)
	umsg.End()
end)

hook.Add("DoPlayerDeath", "gStats.DoPlayerDeath", function( v, k, d )
	if k == v or !k:IsValid() or !v:IsValid() or !k:IsPlayer() then return end
	local points
	if k.Stats["Points"] > v.Stats["Points"] then
		points = math.pow(k.Stats["Points"] + v.Stats["Points"], 2) / math.pow(k.Stats["Points"], 2)
	else
		points = math.pow(v.Stats["Points"] + k.Stats["Points"], 2) / math.pow(v.Stats["Points"], 2) * v.Stats["Points"] / k.Stats["Points"]
	end
	points = math.Round(points)
	k.Stats["GotHeadShot"] = false
	if k.Stats["GotHeadShot"] then
		k.Stats["GotHeadShot"] = false
		k:UpdateHeadshots()
		k:UpdateKills()
	else
		k:UpdateKills()
		k.Stats["GotHeadShot"] = false
	end
	v:UpdatePoints(-points)
	k:UpdatePoints(points)
	v:UpdateDeaths()
	timer.Simple(1, function()
		for _k, _v in pairs(player.GetAll()) do
			chat.AddText(_v, Color(25, 151, 25), "[gStats] ", Color(249, 247, 237), k:Nick() .. "(" .. k.Stats["Points"] .. ")" .. " got " .. points .. " points for killing " .. v:Nick() .. "(" .. v.Stats["Points"] .. ")")
		end
	end)
end)

hook.Add("ScalePlayerDamage", "gStats.ScalePlayerDamage", function( p, hit, dmg )
	if p:IsValid() and dmg:GetInflictor():IsValid() and p != dmg:GetInflictor() then
		if hit == HITGROUP_HEAD then
			dmg:GetInflictor().Stats["GotHeadShot"] = true
			dmg:ScaleDamage(1)
		else
			dmg:GetInflictor().Stats["GotHeadShot"] = false
			dmg:ScaleDamage(1)
		end
	 end
end)

hook.Add("PlayerSay", "gStats.PlayerSay", function( p, txt, tm )
	if string.sub(txt, 1, 8) == "!session" then
		p:Session()
		if !SilentCommands then
			return "!session"
		else
			return ""
		end
	end
	if string.sub(txt, 1, 5) == "!rank" then
		p:Rank()
		if !SilentCommands then
			return "!rank"
		else
			return ""
		end
	end
	if string.sub(txt, 1, 4) == "!top" then
		p:Top10()
		if !SilentCommands then
			return "!top"
		else
			return ""
		end
	end
	if string.sub(txt, 1, 6) == "!top10" then
		p:Top10()
		if !SilentCommands then
			return "!top10"
		else
			return ""
		end
	end
	if string.sub(txt, 1, 6) == "!reset" then
		if !p.Waiting then
			chat.AddText(p, Color(25, 151, 25), "[gStats] ", Color(249, 247, 237), "Are you sure you wish to reset your stats(!yes).")
			p.Waiting = true
			if !SilentCommands then
				return "!reset"
			else
				return ""
			end
		end
	end
	if string.sub(txt, 1, 4) == "!yes" then
		if p.Waiting then
			chat.AddText(p, Color(25, 151, 25), "[gStats] ", Color(249, 247, 237), "Your stats have been reset.")
			p:ResetData( )
			p.Waiting = false
			if !SilentCommands then
				return "!yes"
			else
				return ""
			end
		end
	end
end)

hook.Add("PlayerDisconnected", "gStats.PlayerDisconnected", function( p )
	p:SetData()
	chat.AddText(p, Color(25, 151, 25), "[gStats] ", Color(249, 247, 237), "Player statistics have been saved.")
end)

hook.Add("ShutDown", "gStats.ShutDown", function()
	for k, v in pairs(player.GetAll()) do
		v:SetData()
		chat.AddText(v, Color(25, 151, 25), "[gStats] ", Color(249, 247, 237), "Player statistics have been saved.")
	end
end)

hook.Add("InitPostEntity", "gStats.InitPostEntity", function()
	timer.Create("ForceSave", 120, 0 , function()
		for k, v in pairs(player.GetAll()) do
			v:SetData()
			chat.AddText(v, Color(25, 151, 25), "[gStats] ", Color(249, 247, 237), "Player statistics have been saved.")
		end
	end)
end)

local players = {}
hook.Add("Think", "gStats.Think", function()
	for k, v in pairs(player.GetAll()) do
		if v:Team() != 1002 then return end
		if v:GetObserverMode() == OBS_MODE_CHASE and v:GetObserverTarget():IsPlayer() and v:GetObserverTarget() != v then
			if SpectatorStats then
				local p = v:GetObserverTarget()
					if !table.HasValue(players, p) then
					tmysql.query("SELECT kills, deaths, points FROM players WHERE steamid='" .. p:SteamID() .. "'", function( Args )
						if Args and Args[1] then
							print("Adding player to players table.")
							local kills = tonumber(Args[1][1])
							local deaths = tonumber(Args[1][2])
							local points = tonumber(Args[1][3])
							umsg.Start("gStats.Spectate", v)
								umsg.String(p.Stats["Rank"] .. ";" .. points .. ";" .. kills .. ";" .. deaths)
							umsg.End()
							table.insert(players, p)
						end
					end)
				end
			end
		end
	end
end)